home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2004 April / Gamestar_61_2004-04_dvdb.iso / DVDStar / Editace / hltp.exe / {app} / Source Code / Half-Life Model Viewer / src / mdlviewer.cpp < prev    next >
C/C++ Source or Header  |  2002-01-15  |  14KB  |  630 lines

  1. //
  2. //                 Half-Life Model Viewer (c) 1999 by Mete Ciragan
  3. //
  4. // file:           mdlviewer.cpp
  5. // last modified:  Jun 03 1999, Mete Ciragan
  6. // copyright:      The programs and associated files contained in this
  7. //                 distribution were developed by Mete Ciragan. The programs
  8. //                 are not in the public domain, but they are freely
  9. //                 distributable without licensing fees. These programs are
  10. //                 provided without guarantee or warrantee expressed or
  11. //                 implied.
  12. //
  13. // version:        1.2
  14. //
  15. // email:          mete@swissquake.ch
  16. // web:            http://www.swissquake.ch/chumbalum-soft/
  17. //
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <mx/mx.h>
  22. #include <mx/gl.h>
  23. #include <mx/mxTga.h>
  24. #include "mdlviewer.h"
  25. #include "GlWindow.h"
  26. #include "ControlPanel.h"
  27. #include "StudioModel.h"
  28. #include "pakviewer.h"
  29. #include "FileAssociation.h"
  30.  
  31.  
  32.  
  33. extern bool bFilterTextures;
  34.  
  35.  
  36.  
  37. MDLViewer *g_MDLViewer = 0;
  38. char g_appTitle[] = "Half-Life Model Viewer v1.25";
  39. static char recentFiles[8][256] = { "", "", "", "", "", "", "", "" };
  40.  
  41.  
  42.  
  43. void
  44. MDLViewer::initRecentFiles ()
  45. {
  46.     for (int i = 0; i < 8; i++)
  47.     {
  48.         if (strlen (recentFiles[i]))
  49.         {
  50.             mb->modify (IDC_FILE_RECENTMODELS1 + i, IDC_FILE_RECENTMODELS1 + i, recentFiles[i]);
  51.         }
  52.         else
  53.         {
  54.             mb->modify (IDC_FILE_RECENTMODELS1 + i, IDC_FILE_RECENTMODELS1 + i, "(empty)");
  55.             mb->setEnabled (IDC_FILE_RECENTMODELS1 + i, false);
  56.         }
  57.     }
  58. }
  59.  
  60.  
  61.  
  62. void
  63. MDLViewer::loadRecentFiles ()
  64. {
  65.     char path[256];
  66.     strcpy (path, mx::getApplicationPath ());
  67.     strcat (path, "/hlmv.rf");
  68.     FILE *file = fopen (path, "rb");
  69.     if (file)
  70.     {
  71.         fread (recentFiles, sizeof recentFiles, 1, file);
  72.         fclose (file);
  73.     }
  74. }
  75.  
  76.  
  77.  
  78. void
  79. MDLViewer::saveRecentFiles ()
  80. {
  81.     char path[256];
  82.  
  83.     strcpy (path, mx::getApplicationPath ());
  84.     strcat (path, "/hlmv.rf");
  85.  
  86.     FILE *file = fopen (path, "wb");
  87.     if (file)
  88.     {
  89.         fwrite (recentFiles, sizeof recentFiles, 1, file);
  90.         fclose (file);
  91.     }
  92. }
  93.  
  94.  
  95.  
  96. bool
  97. swap3dfxgl (bool b)
  98. {
  99. #ifdef WIN32__
  100.     //
  101.     // rename opengl drivers to 3dfxgl
  102.     //
  103.     char szName[256], szPath[256];
  104.  
  105.     strcpy (szName, mx::getApplicationPath ());
  106.     GetCurrentDirectory (256, szPath);
  107.     SetCurrentDirectory (szName);
  108.  
  109.     BOOL ret = TRUE;
  110.     if (b)
  111.     {
  112.         ret &= CopyFile ("3dfxgl.dll", "opengl32.dll", FALSE);
  113.         ret &= DeleteFile ("3dfxgl.dll");
  114.     }
  115.     else
  116.     {
  117.         ret &= CopyFile ("opengl32.dll", "3dfxgl.dll", FALSE);
  118.         ret &= DeleteFile ("opengl32.dll");
  119.     }
  120.  
  121.     SetCurrentDirectory (szPath);
  122.  
  123.     return (ret == TRUE);
  124. #else
  125.     return TRUE;
  126. #endif
  127. }
  128.  
  129.  
  130.  
  131. MDLViewer::MDLViewer ()
  132. : mxWindow (0, 0, 0, 0, 0, g_appTitle, mxWindow::Normal)
  133. {
  134.     // create menu stuff
  135.     mb = new mxMenuBar (this);
  136.     mxMenu *menuFile = new mxMenu ();
  137.     mxMenu *menuOptions = new mxMenu ();
  138.     mxMenu *menuView = new mxMenu ();
  139.     mxMenu *menuHelp = new mxMenu ();
  140.  
  141.     mb->addMenu ("File", menuFile);
  142.     mb->addMenu ("Options", menuOptions);
  143.     mb->addMenu ("View", menuView);
  144.     mb->addMenu ("Help", menuHelp);
  145.  
  146.     mxMenu *menuRecentModels = new mxMenu ();
  147.     menuRecentModels->add ("(empty)", IDC_FILE_RECENTMODELS1);
  148.     menuRecentModels->add ("(empty)", IDC_FILE_RECENTMODELS2);
  149.     menuRecentModels->add ("(empty)", IDC_FILE_RECENTMODELS3);
  150.     menuRecentModels->add ("(empty)", IDC_FILE_RECENTMODELS4);
  151.  
  152.     mxMenu *menuRecentPakFiles = new mxMenu ();
  153.     menuRecentPakFiles->add ("(empty)", IDC_FILE_RECENTPAKFILES1);
  154.     menuRecentPakFiles->add ("(empty)", IDC_FILE_RECENTPAKFILES2);
  155.     menuRecentPakFiles->add ("(empty)", IDC_FILE_RECENTPAKFILES3);
  156.     menuRecentPakFiles->add ("(empty)", IDC_FILE_RECENTPAKFILES4);
  157.  
  158.     menuFile->add ("Load Model...", IDC_FILE_LOADMODEL);
  159.     menuFile->addSeparator ();
  160.     menuFile->add ("Load Background Texture...", IDC_FILE_LOADBACKGROUNDTEX);
  161.     menuFile->add ("Load Ground Texture...", IDC_FILE_LOADGROUNDTEX);
  162.     menuFile->addSeparator ();
  163.     menuFile->add ("Unload Ground Texture", IDC_FILE_UNLOADGROUNDTEX);
  164.     menuFile->addSeparator ();
  165.     menuFile->add ("Open PAK file...", IDC_FILE_OPENPAKFILE);
  166.     menuFile->add ("Close PAK file", IDC_FILE_CLOSEPAKFILE);
  167.     menuFile->addSeparator ();
  168.     menuFile->addMenu ("Recent Models", menuRecentModels);
  169.     menuFile->addMenu ("Recent PAK files", menuRecentPakFiles);
  170.     menuFile->addSeparator ();
  171.     menuFile->add ("Exit", IDC_FILE_EXIT);
  172.  
  173.     menuOptions->add ("Background Color...", IDC_OPTIONS_COLORBACKGROUND);
  174.     menuOptions->add ("Ground Color...", IDC_OPTIONS_COLORGROUND);
  175.     menuOptions->add ("Light Color...", IDC_OPTIONS_COLORLIGHT);
  176.     menuOptions->addSeparator ();
  177.     menuOptions->add ("Filter Textures", IDC_OPTIONS_FILTERTEXTURES);
  178.     menuOptions->addSeparator ();
  179.     menuOptions->add ("Center View", IDC_OPTIONS_CENTERVIEW);
  180. #ifdef WIN32
  181.     menuOptions->addSeparator ();
  182.     menuOptions->add ("Make Screenshot...", IDC_OPTIONS_MAKESCREENSHOT);
  183.     //menuOptions->add ("Dump Model Info", IDC_OPTIONS_DUMP);
  184. #endif
  185.  
  186.     menuView->add ("File Associations...", IDC_VIEW_FILEASSOCIATIONS);
  187.  
  188. #ifdef WIN32
  189.     menuHelp->add ("Goto Homepage...", IDC_HELP_GOTOHOMEPAGE);
  190.     menuHelp->addSeparator ();
  191. #endif
  192.     menuHelp->add ("About...", IDC_HELP_ABOUT);
  193.  
  194.     mb->setChecked (IDC_OPTIONS_FILTERTEXTURES, bFilterTextures);
  195.  
  196.     // create the OpenGL window
  197.     d_GlWindow = new GlWindow (this, 0, 0, 0, 0, "", mxWindow::Normal);
  198. #ifdef WIN32
  199.     SetWindowLong ((HWND) d_GlWindow->getHandle (), GWL_EXSTYLE, WS_EX_CLIENTEDGE);
  200. #endif
  201.  
  202.     d_cpl = new ControlPanel (this);
  203.     d_cpl->setGlWindow (d_GlWindow);
  204.     g_GlWindow = d_GlWindow;
  205.  
  206.     // finally create the pakviewer window
  207.     d_PAKViewer = new PAKViewer (this);
  208.     g_FileAssociation = new FileAssociation ();
  209.  
  210.     loadRecentFiles ();
  211.     initRecentFiles ();
  212.  
  213.     setBounds (20, 20, 640, 540);
  214.     setVisible (true);
  215. }
  216.  
  217.  
  218.  
  219. MDLViewer::~MDLViewer ()
  220. {
  221.     saveRecentFiles ();
  222.     //SaveViewerSettings ("hlmv.cfg");
  223.  
  224.     swap3dfxgl (false);
  225.  
  226. #ifdef WIN32
  227.     //DeleteFile ("hlmv.cfg");
  228.     DeleteFile ("midump.txt");
  229. #endif
  230. }
  231.  
  232.  
  233.  
  234. int
  235. MDLViewer::handleEvent (mxEvent *event)
  236. {
  237.     switch (event->event)
  238.     {
  239.     case mxEvent::Action:
  240.     {
  241.         switch (event->action)
  242.         {
  243.         case IDC_FILE_LOADMODEL:
  244.         {
  245.             const char *ptr = mxGetOpenFileName (this, 0, "*.mdl");
  246.             if (ptr)
  247.             {
  248.                 int i;
  249.                 d_cpl->loadModel (ptr);
  250.  
  251.                 for (i = 0; i < 4; i++)
  252.                 {
  253.                     if (!mx_strcasecmp (recentFiles[i], ptr))
  254.                         break;
  255.                 }
  256.  
  257.                 // swap existing recent file
  258.                 if (i < 4)
  259.                 {
  260.                     char tmp[256];
  261.                     strcpy (tmp, recentFiles[0]);
  262.                     strcpy (recentFiles[0], recentFiles[i]);
  263.                     strcpy (recentFiles[i], tmp);
  264.                 }
  265.  
  266.                 // insert recent file
  267.                 else
  268.                 {
  269.                     for (i = 3; i > 0; i--)
  270.                         strcpy (recentFiles[i], recentFiles[i - 1]);
  271.  
  272.                     strcpy (recentFiles[0], ptr);
  273.                 }
  274.  
  275.                 initRecentFiles ();
  276.             }
  277.         }
  278.         break;
  279.  
  280.         case IDC_FILE_LOADBACKGROUNDTEX:
  281.         case IDC_FILE_LOADGROUNDTEX:
  282.         {
  283.             const char *ptr = mxGetOpenFileName (this, 0, "*.*");
  284.             if (ptr)
  285.             {
  286.                 if (d_GlWindow->loadTexture (ptr, event->action - IDC_FILE_LOADBACKGROUNDTEX))
  287.                 {
  288.                     if (event->action == IDC_FILE_LOADBACKGROUNDTEX)
  289.                         d_cpl->setShowBackground (true);
  290.                     else
  291.                         d_cpl->setShowGround (true);
  292.  
  293.                 }
  294.                 else
  295.                     mxMessageBox (this, "Error loading texture.", g_appTitle, MX_MB_OK | MX_MB_ERROR);
  296.             }
  297.         }
  298.         break;
  299.  
  300.         case IDC_FILE_UNLOADGROUNDTEX:
  301.         {
  302.             d_GlWindow->loadTexture (0, 1);
  303.             d_cpl->setShowGround (false);
  304.         }
  305.         break;
  306.  
  307.         case IDC_FILE_OPENPAKFILE:
  308.         {
  309.             const char *ptr = mxGetOpenFileName (this, "\\sierra\\half-life\\valve", "*.pak");
  310.             if (ptr)
  311.             {
  312.                 int i;
  313.  
  314.                 d_PAKViewer->openPAKFile (ptr);
  315.  
  316.                 for (i = 4; i < 8; i++)
  317.                 {
  318.                     if (!mx_strcasecmp (recentFiles[i], ptr))
  319.                         break;
  320.                 }
  321.  
  322.                 // swap existing recent file
  323.                 if (i < 8)
  324.                 {
  325.                     char tmp[256];
  326.                     strcpy (tmp, recentFiles[4]);
  327.                     strcpy (recentFiles[4], recentFiles[i]);
  328.                     strcpy (recentFiles[i], tmp);
  329.                 }
  330.  
  331.                 // insert recent file
  332.                 else
  333.                 {
  334.                     for (i = 7; i > 4; i--)
  335.                         strcpy (recentFiles[i], recentFiles[i - 1]);
  336.  
  337.                     strcpy (recentFiles[4], ptr);
  338.                 }
  339.  
  340.                 initRecentFiles ();
  341.  
  342.                 redraw ();
  343.             }
  344.         }
  345.         break;
  346.  
  347.         case IDC_FILE_CLOSEPAKFILE:
  348.         {
  349.             d_PAKViewer->closePAKFile ();
  350.             redraw ();
  351.         }
  352.         break;
  353.  
  354.         case IDC_FILE_RECENTMODELS1:
  355.         case IDC_FILE_RECENTMODELS2:
  356.         case IDC_FILE_RECENTMODELS3:
  357.         case IDC_FILE_RECENTMODELS4:
  358.         {
  359.             int i = event->action - IDC_FILE_RECENTMODELS1;
  360.             d_cpl->loadModel (recentFiles[i]);
  361.  
  362.             char tmp[256];            
  363.             strcpy (tmp, recentFiles[0]);
  364.             strcpy (recentFiles[0], recentFiles[i]);
  365.             strcpy (recentFiles[i], tmp);
  366.  
  367.             initRecentFiles ();
  368.  
  369.             redraw ();
  370.         }
  371.         break;
  372.  
  373.         case IDC_FILE_RECENTPAKFILES1:
  374.         case IDC_FILE_RECENTPAKFILES2:
  375.         case IDC_FILE_RECENTPAKFILES3:
  376.         case IDC_FILE_RECENTPAKFILES4:
  377.         {
  378.             int i = event->action - IDC_FILE_RECENTPAKFILES1 + 4;
  379.             d_PAKViewer->openPAKFile (recentFiles[i]);
  380.  
  381.             char tmp[256];            
  382.             strcpy (tmp, recentFiles[4]);
  383.             strcpy (recentFiles[4], recentFiles[i]);
  384.             strcpy (recentFiles[i], tmp);
  385.  
  386.             initRecentFiles ();
  387.  
  388.             redraw ();
  389.         }
  390.         break;
  391.  
  392.         case IDC_FILE_EXIT:
  393.         {
  394.             d_PAKViewer->closePAKFile ();
  395.             redraw ();
  396.             mx::quit ();
  397.         }
  398.         break;
  399.  
  400.         case IDC_OPTIONS_COLORBACKGROUND:
  401.         case IDC_OPTIONS_COLORGROUND:
  402.         case IDC_OPTIONS_COLORLIGHT:
  403.         {
  404.             float *cols[3] = { g_viewerSettings.bgColor, g_viewerSettings.gColor, g_viewerSettings.lColor };
  405.             float *col = cols[event->action - IDC_OPTIONS_COLORBACKGROUND];
  406.             int r = (int) (col[0] * 255.0f);
  407.             int g = (int) (col[1] * 255.0f);
  408.             int b = (int) (col[2] * 255.0f);
  409.             if (mxChooseColor (this, &r, &g, &b))
  410.             {
  411.                 col[0] = (float) r / 255.0f;
  412.                 col[1] = (float) g / 255.0f;
  413.                 col[2] = (float) b / 255.0f;
  414.             }
  415.         }
  416.         break;
  417.  
  418.         case IDC_OPTIONS_CENTERVIEW:
  419.             d_cpl->centerView ();
  420.             break;
  421.  
  422.         case IDC_OPTIONS_MAKESCREENSHOT:
  423.         {
  424.             char *ptr = (char *) mxGetSaveFileName (this, "", "*.tga");
  425.             if (ptr)
  426.             {
  427.                 if (!strstr (ptr, ".tga"))
  428.                     strcat (ptr, ".tga");
  429.                 d_GlWindow->dumpViewport (ptr);
  430.             }
  431.         }
  432.         break;
  433.  
  434.         case IDC_OPTIONS_FILTERTEXTURES:
  435.             bFilterTextures = !mb->isChecked (IDC_OPTIONS_FILTERTEXTURES);
  436.             mb->setChecked (IDC_OPTIONS_FILTERTEXTURES, bFilterTextures);
  437.             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, bFilterTextures ? GL_LINEAR:GL_NEAREST);
  438.             glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, bFilterTextures ? GL_LINEAR:GL_NEAREST);
  439.             break;
  440.  
  441.         case IDC_OPTIONS_DUMP:
  442.             d_cpl->dumpModelInfo ();
  443.             break;
  444.  
  445.         case IDC_VIEW_FILEASSOCIATIONS:
  446.             g_FileAssociation->setAssociation (0);
  447.             g_FileAssociation->setVisible (true);
  448.             break;
  449.  
  450. #ifdef WIN32
  451.         case IDC_HELP_GOTOHOMEPAGE:
  452.             ShellExecute (0, "open", "http://www.swissquake.ch/chumbalum-soft/index.html", 0, 0, SW_SHOW);
  453.             break;
  454. #endif
  455.  
  456.         case IDC_HELP_ABOUT:
  457.             mxMessageBox (this,
  458.                 "Half-Life Model Viewer v1.25 (c) 2002 by Mete Ciragan\n\n"
  459.                 "Left-drag to rotate.\n"
  460.                 "Right-drag to zoom.\n"
  461.                 "Shift-left-drag to x-y-pan.\n\n"
  462.                 "Build:\t" __DATE__ ".\n"
  463.                 "Email:\tmete@swissquake.ch\n"
  464.                 "Web:\thttp://www.swissquake.ch/chumbalum-soft/", "About Half-Life Model Viewer",
  465.                 MX_MB_OK | MX_MB_INFORMATION);
  466.             break;
  467.         
  468.         } //switch (event->action)
  469.  
  470.     } // mxEvent::Action
  471.     break;
  472.  
  473.     case mxEvent::Size:
  474.     {
  475.         int w = event->width;
  476.         int h = event->height;
  477.         int y = mb->getHeight ();
  478. #ifdef WIN32
  479. #define HEIGHT 120
  480. #else
  481. #define HEIGHT 140
  482.         h -= 40;
  483. #endif
  484.  
  485.         if (d_PAKViewer->isVisible ())
  486.         {
  487.             w -= 170;
  488.             d_PAKViewer->setBounds (w, y, 170, h);
  489.         }
  490.  
  491.         d_GlWindow->setBounds (0, y, w, h - HEIGHT);
  492.         d_cpl->setBounds (0, y + h - HEIGHT, w, HEIGHT);
  493.     }
  494.     break;
  495.     } // event->event
  496.  
  497.     return 1;
  498. }
  499.  
  500.  
  501.  
  502. void
  503. MDLViewer::redraw ()
  504. {
  505.     mxEvent event;
  506.     event.event = mxEvent::Size;
  507.     event.width = w2 ();
  508.     event.height = h2 ();
  509.     handleEvent (&event);
  510. }
  511.  
  512.  
  513.  
  514. int
  515. main (int argc, char *argv[])
  516. {
  517.     //
  518.     // make sure, we start in the right directory
  519.     //
  520.     char szName[256];
  521.  
  522.     strcpy (szName, mx::getApplicationPath ());
  523.     mx_setcwd (szName);
  524.  
  525.     char cmdline[1024] = "";
  526.     if (argc > 1)
  527.     {
  528.         strcpy (cmdline, argv[1]);
  529.         for (int i = 2; i < argc; i++)
  530.         {
  531.             strcat (cmdline, " ");
  532.             strcat (cmdline, argv[i]);
  533.         }
  534.     }
  535.  
  536.     if (!strcmp (cmdline, "-fullscreen"))
  537.     {
  538. #ifdef WIN32
  539.         mxGlWindow::setFormat (mxGlWindow::FormatDouble, 32, 24);
  540.         mx::init (argc, argv);
  541.  
  542.         if (!LoadViewerSettings ("hlmv.cfg"))
  543.         {
  544.             mxMessageBox (0, "Error loading configuration.", g_appTitle, MX_MB_OK | MX_MB_ERROR);
  545.             return 0;
  546.         }
  547.  
  548.         if (g_viewerSettings.cds)
  549.             mx::setDisplayMode (g_viewerSettings.width, g_viewerSettings.height, 16);
  550.  
  551.         mxGlWindow::setFormat (mxGlWindow::FormatDouble, 16, 16);
  552.         GlWindow *glw = new GlWindow (0, 0, 0, g_viewerSettings.width, g_viewerSettings.height, "", mxWindow::Popup);
  553.  
  554.         glw->loadTexture (g_viewerSettings.backgroundTexFile, 0);
  555.         glw->loadTexture (g_viewerSettings.groundTexFile, 1);
  556.  
  557.         g_studioModel.FreeModel ();
  558.         if (!g_studioModel.LoadModel (g_viewerSettings.modelFile))
  559.         {
  560.             if (g_viewerSettings.cds)
  561.                 mx::setDisplayMode (0, 0, 0);
  562.             mxMessageBox (0, "Error loading model.", g_appTitle, MX_MB_OK | MX_MB_ERROR);
  563.             exit (-1);
  564.         }
  565.  
  566.         if (!g_studioModel.PostLoadModel (g_viewerSettings.modelFile))
  567.         {
  568.             if (g_viewerSettings.cds)
  569.                 mx::setDisplayMode (0, 0, 0);
  570.             mxMessageBox (0, "Error post-loading model.", g_appTitle, MX_MB_OK | MX_MB_ERROR);
  571.             exit (-1);
  572.         }
  573.  
  574.         g_studioModel.SetSequence (g_viewerSettings.sequence);
  575.  
  576.         int i;
  577.         studiohdr_t *hdr = g_studioModel.getStudioHeader ();
  578.         for (i = 0; i < hdr->numbodyparts; i++)
  579.             g_studioModel.SetBodygroup (i, g_viewerSettings.submodels[i]);
  580.  
  581.         for (i = 0; i < hdr->numbonecontrollers; i++)
  582.         {
  583.             mstudiobonecontroller_t *pbonecontrollers = (mstudiobonecontroller_t *) ((byte *) hdr + hdr->bonecontrollerindex);
  584.             if (pbonecontrollers[i].index == 4)
  585.                 g_studioModel.SetMouth (g_viewerSettings.controllers[i]);
  586.             else
  587.                 g_studioModel.SetController (pbonecontrollers[i].index, g_viewerSettings.controllers[i]);
  588.         }
  589.  
  590.         g_studioModel.SetSkin (g_viewerSettings.skin);
  591.  
  592.         if (g_viewerSettings.speedScale == 0.0f)
  593.             g_viewerSettings.speedScale = 1.0f;
  594.  
  595.         if (g_viewerSettings.use3dfx)
  596.             g_viewerSettings.useStencil = false;
  597.  
  598.         mx::setIdleWindow (glw);
  599.         int ret = mx::run ();
  600.  
  601.         g_studioModel.FreeModel ();
  602.  
  603.         if (g_viewerSettings.cds)
  604.             mx::setDisplayMode (0, 0, 0);
  605.  
  606.         return ret;
  607. #endif
  608.     }
  609.  
  610.     //mx::setDisplayMode (0, 0, 0);
  611.     mx::init (argc, argv);
  612.     g_MDLViewer = new MDLViewer ();
  613.     g_MDLViewer->setMenuBar (g_MDLViewer->getMenuBar ());
  614.     g_MDLViewer->setBounds (20, 20, 640, 540);
  615.     g_MDLViewer->setVisible (true);
  616.  
  617.     //LoadViewerSettings ("hlmv.cfg");
  618.  
  619.     if (strstr (cmdline, ".mdl"))
  620.     {
  621.         g_ControlPanel->loadModel (cmdline);
  622.     }
  623.  
  624.     int ret = mx::run ();
  625.  
  626.     mx::cleanup ();
  627.  
  628.     return ret;
  629. }
  630.